//
//  DocListWindow.m
//  Personal Passlock
//
//  Created by 杨岑 on 5/5/15.
//  Copyright (c) 2015 杨岑. All rights reserved.
//

#import "DocumentListWC.h"
#import "DocumentWC.h"
#import "DocListDataItem.h"
#import "AppiCloud.h"
#import "NSAlert+Ext.h"
#import "MyPreferences.h"
#import "Debug.h"


#define kFILE_EXT   @"pplk"


@interface DocumentListWC ()

@end

@implementation DocumentListWC
{
    NSMetadataQuery* _query;
    NSMutableArray* _docWindows;
    NSString* _renamedName;
}

- (void)awakeFromNib
{
    self.docListDataSource.delegate = self;
    
    _query = [[NSMetadataQuery alloc] init];
    _query.searchScopes = @[NSMetadataQueryUbiquitousDocumentsScope];
    NSString* pattern = [NSString stringWithFormat:@"*.%@", kFILE_EXT];
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K LIKE %@", NSMetadataItemFSNameKey, pattern];
    MyLog(@"%@", pred);
    _query.predicate = pred;
    //NSString* nameKey = NSMetadataItemFSNameKey;
    //_query.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:nameKey ascending:YES]];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdateHandler:) name:NSMetadataQueryDidUpdateNotification object:_query];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:_query];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controlTextDidEndEditing:) name:NSControlTextDidEndEditingNotification object:nil];
    
    NSLog(@"Start query %@", _query);
    [_query startQuery];
}

- (DocListDataItem*)getSelectedDocItem
{
    if (self.docList.selectedRow >= 0)
    {
        DocListDataItem* dataItem = self.docListDataSource.itemList[self.docList.selectedRow];
        return dataItem;
    }
    return nil;
}

- (IBAction)newDoc_click:(id)sender {
    srand((uint)time(0));
    NSString* docName = [NSString stringWithFormat:@"new%d", rand()];
    MyLog(@"New doc name: %@",docName);
    NSError* error;

    NSURL* newDocURL = [[[AppiCloud singleton] formatDocURL:docName] URLByAppendingPathExtension:kFILE_EXT];
    NSFileCoordinator* fc = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
    [fc coordinateWritingItemAtURL:newDocURL options:NSFileCoordinatorWritingForMoving error:&error byAccessor:^(NSURL *newURL) {
        NSError* error;
        NSString* content = [NSString stringWithFormat:@"pplk file created at %@", [NSDate date]];
        [content writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&error];
        if (error)
        {
            [NSAlert runModalSheet:self.window withError:error];
        }
        else
        {
            
        }
    }];
    
    if (error)
    {
        [NSAlert runModalSheet:self.window withError:error];
    }
}

- (IBAction)openDoc_click:(id)sender {
    DocListDataItem* docItem = [self getSelectedDocItem];
    if (!docItem) return;
    
    if (!_docWindows)
    {
        _docWindows = [NSMutableArray array];
    }
    DocumentWC* wc = [[DocumentWC alloc] initWithWindowNibName:@"Document"];
    wc.docURL = docItem.URL;
    [wc loadWindow];
    [wc showWindow:self];
    [_docWindows addObject:wc];
}

- (IBAction)deleteDoc_click:(id)sender {
    DocListDataItem* docItem = [self getSelectedDocItem];
    if (!docItem) return;
    
    NSAlert* alert = [[NSAlert alloc] init];
    [alert addButtonWithTitle:@"OK"];
    [alert addButtonWithTitle:@"Cancel"];
    alert.messageText = [NSString stringWithFormat:@"Do you want to delete \"%@\"?", docItem.name];
    [alert runModalSheet:self.window completionHandler:^(NSModalResponse returnCode) {
        if (returnCode == NSAlertFirstButtonReturn)
        {
            NSError* error;
            NSFileCoordinator* fc = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
            [fc coordinateWritingItemAtURL:docItem.URL options:NSFileCoordinatorWritingForDeleting error:&error byAccessor:^(NSURL *newURL) {
                // Deleting
                NSError* error;
                NSFileManager* fm = [[NSFileManager alloc] init];
                [fm removeItemAtURL:newURL error:&error];
                if (error)
                {
                    [NSAlert runModalSheet:self.window withError:error];
                }
                else
                {
                    docItem.state = DocumentStateNormal;
                }
            }];
            
            if (error)
            {
                [NSAlert runModalSheet:self.window withError:error];
            }
            else
            {
                docItem.state = DocumentStateDeleting;
            }
        }
    }];
}

- (void)controlTextDidEndEditing:(NSNotification *)notification
{
    DocListDataItem* docItem = [self getSelectedDocItem];
    if (!docItem) return;
    
    NSTextField* txt = notification.object;
    if (![txt.identifier isEqualToString:@"doc name"]) return;
    
    NSString* newDocName = txt.stringValue;
    if (!newDocName.length)
    {
        // Don't allow empty name
        txt.stringValue = docItem.name;
        return;
    }
    if ([newDocName isEqualToString:docItem.name]) return;
    
    // Get URL of new name
    NSURL* newDocURL = [[[AppiCloud singleton] formatDocURL:newDocName] URLByAppendingPathExtension:kFILE_EXT];
    NSLog(@"New doc name: %@", newDocURL);
    
    NSError* error;
    NSFileCoordinator* fc = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
    [fc coordinateWritingItemAtURL:docItem.URL options:NSFileCoordinatorWritingForMoving error:&error byAccessor:^(NSURL *newURL) {
        // Renaming
        NSError* error;
        NSFileManager* fm = [[NSFileManager alloc] init];
        [fm moveItemAtURL:newURL toURL:newDocURL error:&error];
        if (error)
        {
            [NSAlert runModalSheet:self.window withError:error];
        }
        else
        {
            _renamedName = newDocName;
            docItem.state = DocumentStateNormal;
            if (docItem.isPrimary)
            {
                docItem.name = newDocName;
                [MyPreferences singleton].primaryDocName = newDocName;
            }
        }
    }];
    
    if (error)
    {
        [NSAlert runModalSheet:self.window withError:error];
    }
    else
    {
        docItem.state = DocumentStateMoving;
    }
}

- (void)dealloc
{
    [_query disableUpdates];
    [_query stopQuery];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:_query];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidUpdateNotification object:_query];
}

- (void)logQueryResult:(NSMetadataQuery*)query
{
    DocListDataItem* primaryDoc;
    NSString* primaryDocName = [MyPreferences singleton].primaryDocName;
    
    [query disableUpdates];
    
    // New list
    NSMutableArray* docItemList = [NSMutableArray array];
    NSLog(@"%@: %ld", query, query.resultCount);
    for (NSMetadataItem* item in query.results)
    {
        //NSLog(@"%@ (%@)", [item valueForAttribute:NSMetadataItemFSNameKey], [item valueForKey:NSMetadataUbiquitousItemDownloadingStatusKey]);
        //NSLog(@"%@", [item valueForAttribute:NSMetadataItemURLKey]);
        
        DocListDataItem* docItem = [DocListDataItem create:item];
        docItem.isPrimary = NSOrderedSame == [docItem.name caseInsensitiveCompare:primaryDocName];
        if (docItem.isPrimary) primaryDoc = docItem;
        if (!docItem.isPrimary) [docItemList addObject:docItem];
    }
    [query enableUpdates];
    
    // Sort by name
    [self sortDocItemList:docItemList];
    // Put the primary doc at top
    if (primaryDoc)
    {
        [docItemList insertObject:primaryDoc atIndex:0];
    }

    DocListDataItem* prevSelectedDoc = [self getSelectedDocItem];
    self.docListDataSource.itemList = docItemList;
    [self.docList noteNumberOfRowsChanged];
    if  (docItemList.count > 0)
    {
        [self reloadDocList];
    }
    
    NSString* prevDocName = _renamedName;
    _renamedName = nil;
    if (!prevDocName) _renamedName = prevSelectedDoc.name;
    if (prevDocName)
    {
        // Try to select the renamed one
        NSUInteger index = [self.docListDataSource.itemList indexOfObjectPassingTest:^BOOL(DocListDataItem* item, NSUInteger idx, BOOL *stop) {
            return NSOrderedSame == [item.name caseInsensitiveCompare:prevDocName];
        }];
        
        if  (index != NSNotFound)
        {
            [self.docList selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
        }
    }
}

- (void)queryDidUpdateHandler:(NSNotification*)notification {
    //NSLog(@">>>queryDidUpdateHandler");
    [self logQueryResult:notification.object];
}

- (void)queryDidFinishGathering:(NSNotification *)notification {
    //NSLog(@">>>queryDidFinishGathering");
    //[_query addObserver:self forKeyPath:@"results" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionInitial context:nil];
    [self logQueryResult:notification.object];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"results"])
    {
        NSLog(@"%@", change);
    }
    //return [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}

- (void)tableViewSelectionDidChange:(NSNotification*)notification
{
    BOOL valid = NO;
    DocListDataItem* docItem = [self getSelectedDocItem];
    if (docItem)
    {
        if (docItem.state != DocumentStateDeleting && docItem.state != DocumentStateMoving
            && docItem.status != DocumentStatusNotLocal)
        {
            valid = YES;
        }
    }
    self.deleteButton.enabled = valid;
    self.openButton.enabled = valid;
    self.setPrimaryButton.enabled = valid && !docItem.isPrimary;
    self.resolveButton.enabled = valid && docItem.inConflict;
}

- (IBAction)setPrimary_click:(id)sender {
    DocListDataItem* docItem = [self getSelectedDocItem];
    if (!docItem) return;
    
    for (DocListDataItem* item in self.docListDataSource.itemList)
    {
        if (item.isPrimary)
        {
            item.isPrimary = NO;
            break;
        }
    }
    docItem.isPrimary = YES;
    [MyPreferences singleton].primaryDocName = docItem.name;
    
    [self.docListDataSource.itemList removeObject:docItem];
    [self sortDocItemList:self.docListDataSource.itemList];
    [self.docListDataSource.itemList insertObject:docItem atIndex:0];
    [self reloadDocList];

    [self.docList selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
}

- (void)reloadDocListItemAt:(NSInteger)row
{
    NSIndexSet* rows = [NSIndexSet indexSetWithIndex:row];
    NSIndexSet* columns = [NSIndexSet indexSetWithIndex:0];
    [self.docList reloadDataForRowIndexes:rows columnIndexes:columns];
}

- (void)reloadDocList
{
    NSIndexSet* rows = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.docListDataSource.itemList.count)];
    NSIndexSet* cols = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
    [self.docList reloadDataForRowIndexes:rows columnIndexes:cols];
}

- (void)sortDocItemList:(NSMutableArray*)docItemList
{
    [docItemList sortUsingComparator:^NSComparisonResult(DocListDataItem* a, DocListDataItem* b) {
        return [a.name caseInsensitiveCompare:b.name];
    }];
}

@end
